package com.onegene.pdf.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.system.HostInfo;
import cn.hutool.system.SystemUtil;
import com.onegene.pdf.component.AbstractReportBuilder;
import com.onegene.pdf.component.config.CommonParam;
import com.onegene.pdf.component.entity.*;
import com.onegene.pdf.component.factory.ReportBuilderContext;
import com.onegene.pdf.component.factory.ReportFactory;
import com.onegene.pdf.component.report.CommonHandler;
import com.onegene.pdf.entity.SampleResult;
import com.onegene.pdf.job.EverydayBatchExport;
import com.onegene.pdf.job.EverydayExport;
import com.onegene.pdf.job.support.ExportParam;
import com.onegene.pdf.service.CommonService;
import com.onegene.pdf.service.DownLoadSerivce;
import com.onegene.pdf.util.Precondition;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * @author: laoliangliang
 * @description:
 * @create: 2020/5/29 8:31
 **/
@RestController
@RequestMapping("/pdf")
@Slf4j
public class DownloadPdfController {

    @Autowired
    private EverydayExport everydayExport;

    @Autowired
    private EverydayBatchExport everydayBatchExport;

    @Autowired
    private DownLoadSerivce downLoadSerivce;

    @Autowired
    private CommonService commonService;

    @Autowired
    private CommonParam commonParam;

    @Autowired
    private ApplicationContext applicationContext;

    @PostConstruct
    public void init() {
        HostInfo hostInfo = SystemUtil.getHostInfo();
        String name = hostInfo.getName();
        if ("laoliangliangdeMacBook-Pro.local".equals(name)) {
            commonParam.fontPath = "/Users/laoliangliang" + commonParam.fontPath;
            commonParam.prefixPath = "/Users/laoliangliang" + commonParam.prefixPath;
        }

        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", commonParam.parallelism);

        // 初始化创建文件夹
        createDirectory();
    }

    public void createDirectory() {
        File prefixPathFile = new File(commonParam.prefixPath);
        if (!prefixPathFile.exists()) {
            prefixPathFile.mkdirs();
        }
    }

    @Scheduled(cron = "0 0 0 * * ?")
    public void clearDirectory() {
        String prefix = commonParam.prefixPath + "target" + "/";
        FileUtil.del(new File(prefix));
    }

    /**
     * @param token token值
     * @param uuid  uuid值
     * @param type  报告类型 0-易感  1-用药 2-简化版
     * @param part  部分
     * @param force 强制重新生成
     */
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public Result downLoad(@RequestParam("access_token") String token,
                           @RequestParam("uuid") String uuid,
                           @RequestParam(value = "type", defaultValue = "0") Integer type,
                           @RequestParam(value = "part", defaultValue = "0") Integer part,
                           @RequestParam(value = "force", defaultValue = "0") Integer force,
                           @RequestParam(value = "logoCode", defaultValue = "") String logoCode,
                           @RequestParam(value = "version", defaultValue = "1") Integer version,
                           @RequestParam(value = "all", defaultValue = "false") Boolean all,
                           HttpServletResponse response) throws IOException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        // 报告数据获取
        PrintReportBean printReportBean = null;
        EarlyReportBean earlyReportBean = null;
        if (type < 3) {
            printReportBean = commonService.getGeneReportBean(token, uuid, type);
            Precondition.checkNotNull(printReportBean, "报告数据不存在");
        }else{
            earlyReportBean = commonService.getEarlyReportBean(token, uuid, type);
            Precondition.checkNotNull(earlyReportBean, "报告数据不存在");
        }

        // 查询样本用来改名
        SampleResult sampleResult = commonService.getSampleResult(uuid);
        String prefix = commonParam.prefixPath + "target/" + commonParam.profile + "/";
        String outPath = prefix + sampleResult.toString() + ".pdf";
        // 参数组装
        ReportBuilderContext builderContext = getReportBuilderContext(type, part, logoCode, outPath, version, all,sampleResult);

        // 判断文件是否存在，存在则直接读取返回
        if (existOutput(outPath, force, response, sampleResult)) {
            stopWatch.stop();
            log.info("耗时：" + stopWatch.getTotalTimeMillis() + "ms");
            return Result.ok();
        }

        // 报告构建器创建
        AbstractReportBuilder builder = ReportFactory.create(builderContext);
        if (printReportBean != null) {
            builder.buildAll(printReportBean);
        }
        if (earlyReportBean != null) {
            builder.buildAll(earlyReportBean);
        }

        // 输出
        writeOutputStream(sampleResult.toString(), response, outPath);
        stopWatch.stop();
        log.info("耗时：" + stopWatch.getTotalTimeMillis() + "ms");
        return Result.ok();
    }

    @RequestMapping(value = "/disk", method = RequestMethod.POST)
    @Async
    public Result saveToDisk(@RequestBody PdfRequest pdfRequest) {
        downLoadSerivce.saveToDisk(pdfRequest);
        return Result.ok();
    }

    @RequestMapping(value = "/everyday", method = RequestMethod.GET)
    public void runJob(@RequestParam(value = "days", defaultValue = "1") Integer days) {
        ExportParam exportParam = new ExportParam();
        exportParam.setDays(days);
        everydayExport.run(exportParam);
    }

    @RequestMapping(value = "/everydayBatch", method = RequestMethod.GET)
    public void everydayBatch(@RequestParam(value = "days", defaultValue = "1") Integer days) {
        ExportParam exportParam = new ExportParam();
        exportParam.setDays(days);
        everydayBatchExport.run(exportParam);
    }

    private Boolean existOutput(String outPath, Integer force, HttpServletResponse response, SampleResult sampleResult) throws IOException {
        // 若生成则直接返回
        if (Files.exists(Paths.get(outPath)) && (force == null || force != 1)) {
            // 输出
            return writeOutputStream(sampleResult.toString(), response, outPath);
        }
        return false;
    }

    private ReportBuilderContext getReportBuilderContext(Integer type, Integer part, String logoCode, String outPath, Integer version, Boolean all, SampleResult sampleResult) {
        ReportBuilderContext builderContext = new ReportBuilderContext(type);
        LogoImage logoImage = commonService.getLogoImageUrl(logoCode);
        if (logoImage != null) {
            builderContext.setLogoImageUrl(logoImage.getImageUrl());
            builderContext.setStamperUrl(logoImage.getStamperUrl());
        }
        builderContext.setAll(all);
        builderContext.setPrefixPath(commonParam.prefixPath);
        builderContext.setOutPath(outPath);
        builderContext.setPart(part);
        builderContext.setFontPath(commonParam.fontPath);
        // 用药则查询是成人还是儿童
        if (type == 1) {
            if ("5df9bf0ba9847e7f6faec080".equals(sampleResult.getTemplateRefId())) {
                version = 1;
            } else if ("5cd0d53117dbfa109b6ebcda".equals(sampleResult.getTemplateRefId())) {
                version = 2;
            }
        }
        if (type == 3) {
            Environment environment = applicationContext.getEnvironment();
            String profile = environment.getActiveProfiles()[0];
            version = CommonHandler.setPdfVersion(sampleResult, version, profile);
        }
        builderContext.setVersion(version);
        return builderContext;
    }

    private boolean writeOutputStream(String fileName, HttpServletResponse response, String outPath) throws IOException {
        // 输出
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;fileName=" + new String((fileName + ".pdf").getBytes("UTF-8"), "iso-8859-1"));
//        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline;fileName=" + uuid + ".pdf");
        File file = new File(outPath);
        if (file.exists()) {
            FileUtil.writeToStream(file, response.getOutputStream());
            return true;
        }
        return false;
    }

}
